import 'package:dio/dio.dart' hide Response, FormData;
import 'package:dio/dio.dart' as dio show FormData;
import 'package:get/get.dart';
import 'package:sinosheets/network/config/http_config.dart';
import 'package:sinosheets/network/core/base_response.dart';
import 'package:sinosheets/network/interceptor/interceptor_manager.dart';
import 'package:sinosheets/network/interceptor/network_status_interceptor.dart';
import 'package:sinosheets/utils/lottie_utils.dart';
import 'package:sinosheets/utils/toast_util.dart';
import 'package:sinosheets/network/error/error_handler.dart';
import 'package:sinosheets/utils/common_utils/log_util.dart';

class HttpClient {
  /// 单例
  static final HttpClient _instance = HttpClient._internal();
  factory HttpClient() => _instance;

  /// Dio实例
  late final Dio _dio;

  /// 拦截器管理器
  late final InterceptorManager _interceptorManager;

  /// 请求取消令牌管理
  final Map<String, CancelToken> _cancelTokens = {};

  HttpClient._internal();

  /// 初始化网络客户端
  void init(String baseUrl) {
    // 1. 初始化网络状态管理器
    Get.put(NetworkManager());

    // 2. 初始化HTTP配置
    HttpConfig.init(baseUrl: baseUrl);

    // 3. 初始化Dio
    _dio = Dio(BaseOptions(
      baseUrl: HttpConfig.baseUrl,
      connectTimeout: HttpConfig.connectTimeout,
      receiveTimeout: HttpConfig.receiveTimeout,
      sendTimeout: HttpConfig.sendTimeout,
      contentType: HttpConfig.contentType,
      headers: HttpConfig.getDefaultHeaders(),
    ));

    // 4. 初始化并添加拦截器
    _interceptorManager = InterceptorManager();
    _interceptorManager.addTo(_dio);
  }

  /// 发起请求
  Future<BaseResponse> request(
    String path,
    HttpMethod method, {
    Map? parameters,
    bool isShowLoading = false,
    bool isShowToast = true,
    CancelToken? cancelToken,
  }) async {
    if (!NetworkManager.instance.hasConnection) {
      return BaseResponse(code: 1000, msg: 'Network Error，Please try again later', data: null);
    }

    if (isShowLoading) LottieUtils.showToastLoading();

    try {
      final requestCancelToken = cancelToken ?? CancelToken();
      _cancelTokens[path] = requestCancelToken;

      Object? data;
      Map<String, dynamic>? queryParameters;
      switch (method) {
        case HttpMethod.get:
        case HttpMethod.delete:
          queryParameters = {...?parameters};
          break;
        case HttpMethod.post:
          data = parameters ?? {};
          break;
        case HttpMethod.postFormData:
          if (parameters != null) {
            data = dio.FormData.fromMap({...parameters});
          }
          break;
        case HttpMethod.put:
          data = parameters ?? {};
          break;
      }
      final response = await _dio.request(
        path,
        data: data,
        queryParameters: queryParameters,
        options: Options(
          method: method.value,
          headers: HttpConfig.getDefaultHeaders(),
        ),
        cancelToken: requestCancelToken,
      );

      // 业务层错误
      if (response.data is Map && response.data['code'] != 200) {
        final code = response.data['code'];
        final msg = response.data['msg'] ?? 'Business Error，Please try again later';

        ErrorHandler.handleBusinessError(
          code,
          msg,
          data: response.data['data'],
          rawData: response.data,
        );
        if (isShowToast) ToastUtil.showText(msg);
        _checkError(response);
        return BaseResponse.fromResponse(response);
      }

      // 业务成功
      return BaseResponse.fromResponse(response);
    } on DioException catch (e) {
      //判断e.response是否为空
      if (e.response != null) {
        _checkError(e.response);
        if (isShowToast) {
          String errorMsg = 'System Error，Please try again later'.tr;
          var data = e.response?.data;
          if (data is Map && data['msg'] != null) {
            errorMsg = data['msg'];
          }
          ToastUtil.showText(errorMsg);
        }
      } else {
        if (isShowToast) ToastUtil.showText('System Error，Please try again later'.tr);
      }
      ErrorHandler.handleNetworkError(e);
      return BaseResponse(code: 1000, msg: 'System Error，Please try again later', data: null);
    } catch (e) {
      ErrorHandler.handleUnknownError(e);
      if (isShowToast) ToastUtil.showText('System Error，Please try again later');
      return BaseResponse(code: 1000, msg: 'System Error，Please try again later', data: null);
    } finally {
      _cancelTokens.remove(path);
      if (isShowLoading) LottieUtils.hideToastLoading();
    }
  }

  /// 取消指定请求
  void cancelRequest(String path) {
    _cancelTokens[path]?.cancel();
    _cancelTokens.remove(path);
  }

  /// 取消所有请求
  void cancelAllRequests() {
    _cancelTokens.forEach((_, token) => token.cancel());
    _cancelTokens.clear();
  }

  /// 释放资源
  void dispose() {
    cancelAllRequests();
    _interceptorManager.dispose();
    Get.delete<NetworkManager>();
  }

  ///检查错误code
  void _checkError(dynamic response) async {
    dynamic data = response.data;
    int code = 0;
    if (data is Map && data['code'] != null) {
      code = data['code'] is int ? data['code'] : int.tryParse(data['code'].toString()) ?? 0;
    } else {
      LogUtil.e('Unexpected response.data type: ${data.runtimeType}, value: $data');
    }
    // 401未授权自动登出
    if (code == 401) {
      // 这里假设有logout()方法可用
      // logout();
    }
    // 10000 欠款弹窗
    if (code == 10000) {}
  }
}
